package cn.git.agent.match;

import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.util.Arrays;
import java.util.List;

import static net.bytebuddy.matcher.ElementMatchers.named;

/**
 * @description: 多个类名相等情况匹配
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2024-12-24
 */
public class MultiClassNameMatch implements IndirectMatch {

    /**
     * 需要匹配的类名列表
     */
    private List<String> needMatchClassNameList;

    /**
     * 构造方法
     *
     * @param classNames
     */
    private MultiClassNameMatch(String[] classNames) {
        if (classNames == null || classNames.length == 0) {
            throw new IllegalArgumentException("classNames can not be null or empty");
        }
        this.needMatchClassNameList = Arrays.asList(classNames);
    }

    /**
     * 构建匹配规则
     * eg: named(CLASS_NAME1).or(named(CLASS_NAME2))
     *
     * @return
     */
    @Override
    public ElementMatcher.Junction<? super TypeDescription> buildJunction() {
        ElementMatcher.Junction<? super TypeDescription> junction = null;
        for (String className : needMatchClassNameList) {
            if (junction == null) {
                junction = named(className);
            } else {
                junction = junction.or(named(className));
            }
        }
        return junction;
    }

    /**
     * 用于当前匹配器
     * 用于判断 typeDescription 是否满足 IndirectMatch 的实现
     *
     * @param typeDescription
     * @return
     */
    @Override
    public boolean isMatch(TypeDescription typeDescription) {
        /**
         * 比如 needMatchClassNameList里面是 com.mysql.jdbc.PreparedStatement
         * 而 typeDescription 是 com.mysql.jdbc.PreparedStatement 返回true,否则返回false
         */
        return needMatchClassNameList.contains(typeDescription.getTypeName());
    }

    /**
     * 静态方法构建匹配规则
     *
     * @param classNames 匹配类名称
     * @return
     */
    public static IndirectMatch byMultiClassMatch(String... classNames) {
        return new MultiClassNameMatch(classNames);
    }

}
